﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using JigLibX.Physics;
using JigLibX.Geometry;
using JigLibX.Collision;
using JigLibX.Math;
using JigLibX.Vehicles;


namespace LloydGame
{
    public class PowerUpObject : GameObject
    {
        private String m_powerUpType;
        private TimeSpan m_timeTaken;
        private float m_spinangle = 0.0f;
        private float m_jumpangle = 0.0f;
        private Vector3 m_orginal_pos;
        private float m_timeSinceLastEmittedStar = 0;

        private List<Particle> m_glowParticles;

        #region Properties
        public TimeSpan timeTaken
        {
            get { return m_timeTaken; }
        }
        public String powerUpType
        {
            get { return m_powerUpType; }
        }
        public Vector3 original_pos
        {
            get { return m_orginal_pos; }
        }
        #endregion Properties

        public PowerUpObject( Game p_game, GameWorld p_gameWorld, String p_objectType, Vector3 p_position
                         , Vector3 p_rotation, Vector3 p_scale, bool p_staticFlag, String p_alias, String p_powerUpType) 
            : base(p_game, p_gameWorld, p_objectType, p_position, p_rotation, p_scale, p_staticFlag, p_alias)
        {
            
            m_powerUpType = p_powerUpType;
            m_orginal_pos = p_position;
            loadObjectType("GameContent\\Objects\\" + p_objectType + p_powerUpType + ".txt", p_gameWorld);

            m_glowParticles = p_gameWorld.glowParticleSystem.spawnParticles(3, Vector3.Zero, Vector3.Zero, this);
        }

        protected override bool collision_callbackFn(CollisionSkin skin0, CollisionSkin skin1)
        {
            GameObject obj0 = ((Game1)Game).gameWorld.GetObject(skin0.Owner);
            GameObject obj1 = ((Game1)Game).gameWorld.GetObject(skin1.Owner);
            //Console.WriteLine(m_powerUpType);

            // TODO: Use collision info to spawn particles:
            /*foreach (CollisionInfo colision in skin0.Collisions)
            {
                for (int i = 0; i < colision.PointInfo.Count(); i++)
                {
                    if (colision.PointInfo[i] != null)
                        Console.WriteLine(colision.PointInfo[i].Position);
                }
            }
            */

            if (obj0 == null || obj1 == null)
            {
                //Console.WriteLine("This should not happen! :S");
                return false;
            }
            ScreenFlash pu_sf = null;
            if (obj0 == this && obj1.alias == "LocalCar" && !((Game1)Game).gameWorld.objectsToRemove.Contains(obj0))
            {
                if (m_powerUpType == "NITRO" || powerUpType == "DOUBLEYOURPOINTS")
                {                    
                    ((Game1)Game).gameWorld.markForRemoval(obj0);
                    m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
                    ((Game1)Game).gameWorld.PowerUpsToSpawn.Add(this);
                    ((Game1)Game).gameWorld.gamePlayer.activePowerUps.Add(this);
                    Console.WriteLine(m_powerUpType);
                    if (m_powerUpType == "NITRO")
                    {
                        ((Game1)Game).soundBank.PlayCue("NITRO");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["NITRO"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).powerup_icons, 10.0f, 0);
                        ((Game1)Game).screen_flashes.Add(pu_sf);

                    }
                    else
                    {
                        ((Game1)Game).soundBank.PlayCue("DOUBLEYOURPOINTS");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["DOUBLEYOURPOINTS"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                }
                else if (m_powerUpType == "PUNCH" || m_powerUpType == "REVERSE_KEYS" || m_powerUpType == "SLOW" || m_powerUpType == "DOUBLETHEIRPOINTS" || m_powerUpType == "LOW_FRICTION")
                {
                    Console.WriteLine(m_powerUpType);                    
                    if (m_powerUpType == "PUNCH")
                    {
                        ((Game1)Game).soundBank.PlayCue("PUNCH");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["PUNCH"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "REVERSE_KEYS")
                    {
                        ((Game1)Game).soundBank.PlayCue("REVERSE_KEYS");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["REVERSE_KEYS"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "SLOW")
                    {
                        ((Game1)Game).soundBank.PlayCue("SLOW");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["SLOW"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "LOW_FRICTION")
                    {
                        //((Game1)Game).soundBank.PlayCue("SLOW");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["LOW_FRICTION"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else
                    {
                        ((Game1)Game).soundBank.PlayCue("DOUBLETHEIRPOINTS");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["DOUBLETHEIRPOINTS"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
                    ((Game1)Game).gameWorld.PowerUpsToSpawn.Add(this);
                    ((Game1)Game).gameWorld.markForRemoval(obj0);
                }
            }
            else if (obj1 == this && obj0.alias == "LocalCar" && !((Game1)Game).gameWorld.objectsToRemove.Contains(obj1))
            {
                if (m_powerUpType == "NITRO" || powerUpType == "DOUBLEYOURPOINTS")
                {
                    ((Game1)Game).gameWorld.markForRemoval(obj1);
                    m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
                    ((Game1)Game).gameWorld.PowerUpsToSpawn.Add(this);
                    ((Game1)Game).gameWorld.gamePlayer.activePowerUps.Add(this);
                    Console.WriteLine(m_powerUpType);
                    if (m_powerUpType == "NITRO")
                    {
                        ((Game1)Game).soundBank.PlayCue("NITRO");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["NITRO"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).powerup_icons, 10.0f, 0);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else
                    {
                        ((Game1)Game).soundBank.PlayCue("DOUBLEYOURPOINTS");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["DOUBLEYOURPOINTS"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                }
                else if (m_powerUpType == "PUNCH" || m_powerUpType == "REVERSE_KEYS" || m_powerUpType == "SLOW" || m_powerUpType == "DOUBLETHEIRPOINTS" || m_powerUpType == "LOW_FRICTION")
                {
                    Console.WriteLine(m_powerUpType);
                    if (m_powerUpType == "PUNCH")
                    {
                        ((Game1)Game).soundBank.PlayCue("PUNCH");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["PUNCH"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if(m_powerUpType == "REVERSE_KEYS")
                    {
                        ((Game1)Game).soundBank.PlayCue("REVERSE_KEYS");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["REVERSE_KEYS"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "SLOW")
                    {
                        ((Game1)Game).soundBank.PlayCue("SLOW");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["SLOW"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "LOW_FRICTION")
                    {
                        //((Game1)Game).soundBank.PlayCue("SLOW");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["LOW_FRICTION"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else
                    {
                        ((Game1)Game).soundBank.PlayCue("DOUBLETHEIRPOINTS");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["DOUBLETHEIRPOINTS"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
                    ((Game1)Game).gameWorld.PowerUpsToSpawn.Add(this);
                    ((Game1)Game).gameWorld.markForRemoval(obj1);
                }
            }

            if (obj0 == this && obj1.alias == "RemoteCar" && !((Game1)Game).gameWorld.objectsToRemove.Contains(obj0))
            {
                if (m_powerUpType == "PUNCH" || m_powerUpType == "REVERSE_KEYS" || m_powerUpType == "SLOW" || m_powerUpType == "DOUBLETHEIRPOINTS" || m_powerUpType == "LOW_FRICTION")
                {
                    ((Game1)Game).gameWorld.markForRemoval(obj0);
                    m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
                    ((Game1)Game).gameWorld.PowerUpsToSpawn.Add(this);
                    ((Game1)Game).gameWorld.gamePlayer.activePowerUps.Add(this);
                    //Console.WriteLine(m_powerUpType);
                    if (m_powerUpType == "PUNCH")
                    {
                        ((Game1)Game).soundBank.PlayCue("PUNCH");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["PUNCH"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "REVERSE_KEYS")
                    {
                        ((Game1)Game).soundBank.PlayCue("REVERSE_KEYS");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["REVERSE_KEYS"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).powerup_icons, 10.0f, 4);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "SLOW")
                    {
                        ((Game1)Game).soundBank.PlayCue("SLOW");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["SLOW"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).powerup_icons, 10.0f, 5);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "LOW_FRICTION")
                    {
                        //((Game1)Game).soundBank.PlayCue("SLOW");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["LOW_FRICTION"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).powerup_icons, 10.0f, 2);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else
                    {
                        ((Game1)Game).soundBank.PlayCue("DOUBLETHEIRPOINTS");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["DOUBLEYOURPOINTS"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                }
                else if (m_powerUpType == "NITRO" || powerUpType == "DOUBLEYOURPOINTS")
                {
                    m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
                    ((Game1)Game).gameWorld.PowerUpsToSpawn.Add(this);
                    ((Game1)Game).gameWorld.markForRemoval(obj0);
                    if (m_powerUpType == "DOUBLEYOURPOINTS")
                    {
                        foreach (GamePlayer t_gamer in ((Game1)Game).gameWorld.remotePlayers)
                        {
                            if (t_gamer.carObject.body == obj1.body)
                            {
                                t_gamer.activePowerUps.Add(this);
                                break;
                            }
                        }
                    }
                }
            }
            else if (obj1 == this && obj0.alias == "RemoteCar" && !((Game1)Game).gameWorld.objectsToRemove.Contains(obj1))
            {
                if (m_powerUpType == "PUNCH" || m_powerUpType == "REVERSE_KEYS" || m_powerUpType == "SLOW" || m_powerUpType == "DOUBLETHEIRPOINTS" || m_powerUpType == "LOW_FRICTION")
                {
                    ((Game1)Game).gameWorld.markForRemoval(obj1);
                    m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
                    ((Game1)Game).gameWorld.PowerUpsToSpawn.Add(this);
                    ((Game1)Game).gameWorld.gamePlayer.activePowerUps.Add(this);
                    //Console.WriteLine(m_powerUpType);
                    if (m_powerUpType == "PUNCH")
                    {
                        ((Game1)Game).soundBank.PlayCue("PUNCH");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["PUNCH"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "REVERSE_KEYS")
                    {
                        ((Game1)Game).soundBank.PlayCue("REVERSE_KEYS");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["REVERSE_KEYS"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).powerup_icons, 10.0f, 4);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "SLOW")
                    {
                        ((Game1)Game).soundBank.PlayCue("SLOW");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["SLOW"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).powerup_icons, 10.0f, 5);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else if (m_powerUpType == "LOW_FRICTION")
                    {
                        //((Game1)Game).soundBank.PlayCue("SLOW");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["LOW_FRICTION"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).powerup_icons, 10.0f, 2);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                    else
                    {
                        ((Game1)Game).soundBank.PlayCue("DOUBLETHEIRPOINTS");
                        pu_sf = new ScreenFlash(((Game1)Game), ((Game1)Game).flash_pu["DOUBLEYOURPOINTS"], null, ScreenFlashType.ZoomAndFade, 0.5f, 2.5f);
                        ((Game1)Game).screen_flashes.Add(pu_sf);
                    }
                }
                else if (m_powerUpType == "NITRO" || powerUpType == "DOUBLEYOURPOINTS")
                {
                    m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
                    ((Game1)Game).gameWorld.PowerUpsToSpawn.Add(this);
                    ((Game1)Game).gameWorld.markForRemoval(obj1);
                    if (m_powerUpType == "DOUBLEYOURPOINTS")
                    {
                        foreach (GamePlayer t_gamer in ((Game1)Game).gameWorld.remotePlayers)
                        {
                            if (t_gamer.carObject.body == obj1.body)
                            {
                                t_gamer.activePowerUps.Add(this);
                                break;
                            }
                        }
                    }
                }
            }

            return base.collision_callbackFn(skin0, skin1);
        }
        
        #region Update
        // update the object
        public override void Update(GameTime p_gameTime)
        {
            if (!((Game1)Game).gameWorld.isDebug)
            {
                m_jumpangle += p_gameTime.ElapsedGameTime.Milliseconds * 0.002f;
            }

            m_position = m_orginal_pos;
            m_position.Y += Math.Abs(((float)Math.Sin((double)m_jumpangle)) * 1.2f);

            m_body.MoveTo(m_orginal_pos, Matrix.Identity);

            Matrix o = m_skin.GetPrimitiveLocal(0).Transform.Orientation;

            m_rotation.X = MathHelper.WrapAngle((float)-Math.Asin(MathHelper.Clamp(o.M32, -1.0f, 1.0f)));
            m_rotation.Y = MathHelper.WrapAngle((float)Math.Atan2(o.M31, o.M33));
            m_rotation.Z = MathHelper.WrapAngle((float)Math.Atan2(o.M12, o.M22));

            o = m_body.Orientation;

            m_rotation.X += MathHelper.WrapAngle((float)-Math.Asin(MathHelper.Clamp(o.M32, -1.0f, 1.0f)));
            m_rotation.Y += MathHelper.WrapAngle((float)Math.Atan2(o.M31, o.M33));
            m_rotation.Z += MathHelper.WrapAngle((float)Math.Atan2(o.M12, o.M22));

            m_rotation.Y = m_jumpangle;

            // emit stars and update glow
            if (!((Game1)Game).gameWorld.PowerUpsToSpawn.Contains(this))
            {
                foreach (Particle p in m_glowParticles)
                    p.active = true;

                m_timeSinceLastEmittedStar += p_gameTime.ElapsedGameTime.Milliseconds;
                while (m_timeSinceLastEmittedStar > 200)
                {
                    ((Game1)Game).gameWorld.starParticleSystem.spawnParticles(1, m_position, Vector3.Zero, null);

                    m_timeSinceLastEmittedStar -= 200;
                }
            }
            else
            {
                foreach (Particle p in m_glowParticles)
                    p.active = false;
            }
        }
        #endregion Update
    }
}
